﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Utilities;
using nyxwin.Data.Base;
using nyxwin.Data.Utils;
using nyxwin.Common.Base.Utils;

namespace nyxwin.Data.Discussions
{
    public class DiscussionManager : RemoteBase
    {
        #region Events
        public event EventHandler<GetDiscussionEventArgs> GetDiscussionCompleted;
        public event EventHandler<SendDiscussionMessageEventArgs> SendDiscussionMessageCompleted;
        public event EventHandler<RememberDiscussionPostEventArgs> RememberDiscussionPostCompleted;
        public event EventHandler<DeleteDiscussionPostEventArgs> DeleteDiscussionPostCompleted;
        #endregion

        #region Construction
        public DiscussionManager(string authorizationNick, string authorizationToken)
            : base(authorizationNick, authorizationToken)
        {
            base.InvocationCompleted += DiscussionManagerInvocationCompleted;
        }
        #endregion

        #region GetDiscussion
        public void GetDiscussion(DiscussionQuery query)
        {
            var parameters = new Dictionary<string, string>();

            parameters.Add("id", Convert.ToString(query.DiscussionId));
            parameters.Add("direction", query.Direction);

            // put last entry id, to fetch next/prev messages (based on DiscussionQuery.Direction)
            if (query.LastEntryId.HasValue && (!query.IsFilterUser && !query.IsFilterContents))
            {
                parameters.Add("id_wu", Convert.ToString(query.LastEntryId.Value));
            }
            // put last first id, to fetch next/prev messages (based on DiscussionQuery.Direction)
            if (query.FirstEntryId.HasValue && !query.LastEntryId.HasValue && (!query.IsFilterUser && !query.IsFilterContents))
            {
                parameters.Add("id_wu", Convert.ToString(query.LastEntryId.Value));
            }

            if (query.IsFilterUser || query.IsFilterContents) // search, obviously
            {
                parameters.Add("id_wu", "0");
                if (query.IsFilterUser)
                {
                    parameters.Add("filter_user", query.FilterUser);
                }
                if (query.IsFilterContents)
                {
                    parameters.Add("filter_text", query.FilterContents);
                }
            }

            base.InvokeRemote("discussion", "messages", parameters.ToUrlArray());
        }
        #endregion

        #region SendDiscussionMessage
        public void SendDiscussionMessage(int discussionId, string message)
        {
            var parameters = new Dictionary<string, string>();

            parameters.Add("id", Convert.ToString(discussionId));
            parameters.Add("message", message);

            base.InvokeRemote("discussion", "send", parameters.ToUrlArray());
        }
        #endregion

        #region RememberDiscussionPost
        public void RememberDiscussionPost(int discussionId, int wuId)
        {
            var parameters = new Dictionary<string, string>();

            parameters.Add("id_klub", Convert.ToString(discussionId));
            parameters.Add("id_wu", Convert.ToString(wuId));
            parameters.Add("reminder", "1"); // TODO: ask NYX, if '0' will remove the reminder or not.

            base.InvokeRemote("discussion", "reminder", parameters.ToUrlArray());
        }
        #endregion

        #region DeleteDiscussionPost
        public void DeleteDiscussionPost(int discussionId, int wuId)
        {
            var parameters = new Dictionary<string, string>();

            parameters.Add("id_klub", Convert.ToString(discussionId));
            parameters.Add("id_wu", Convert.ToString(wuId));

            base.InvokeRemote("discussion", "delete", parameters.ToUrlArray());
        }
        #endregion

        #region DiscussionManagerInvocationCompleted
        void DiscussionManagerInvocationCompleted(object sender, InvocationEventArgs e)
        {
            if (e.Method != "discussion")
                throw new NyxException(string.Format("Expected 'discussion', but got '{0}' instead.", e.Method));

            var data = JsonConvert.DeserializeObject(e.Result) as JObject;

            if (e.Parameter == "messages")
            {
                int discussionId = -1;
                string discussionName = string.Empty;
                int? lastVisitId = null;
                bool write = true;
                bool delete = false; /* global delete, a.k.a admin */

                if (data["discussion"] != null)
                {
                    if (data["discussion"]["id_klub"] != null)
                    {
                        discussionId = data["discussion"].Value<int>("id_klub");
                    }

                    if (data["discussion"]["name"] != null)
                    {
                        discussionName = data["discussion"].Value<string>("name");
                    }

                    if (data["discussion"]["last_visit"] != null)
                    {
                        lastVisitId = data["discussion"].Value<int>("last_visit");
                    }

                    if (data["discussion"]["rights"] != null)
                    {
                        var rights = data["discussion"]["rights"];
                        write = 1.Equals(rights.Value<int>("write"));
                        delete = 1.Equals(rights.Value<int>("delete"));
                    }
                }

                if (data["data"] != null)
                {
                    var list = new List<DiscussionPost>();
                    foreach (var row in data["data"])
                    {
                        var post = new DiscussionPost();
                        post.Id = row.Value<int>("id_wu");
                        post.Nick = row.Value<string>("nick");
                        post.Time = row.Value<long>("time");
                        post.MarkedUnread = "yes".Equals(row.Value<string>("new"));
                        post.Rating = row.Value<int>("wu_rating");
                        post.Content = row.Value<string>("content");
                        list.Add(post);
                    }

                    FireGetDiscussionCompleted(new GetDiscussionEventArgs()
                    {
                        DiscussionList = list,
                        Id = discussionId,
                        Name = discussionName,
                        LastVisitId = lastVisitId,
                        CanWrite = write,
                        CanDelete = delete
                    });
                }
                else
                {
                    FireErrorOccurred(new ErrorOccurredEventArgs("Empty result (messages)."));
                }
            }

            if (e.Parameter == "send")
            {
                if (data["result"] != null)
                {
                    var result = "ok".Equals(data["result"].Value<string>());
                    FireSendDiscussionMessageCompleted(new SendDiscussionMessageEventArgs() { Result = result });
                }
                else
                {
                    FireErrorOccurred(new ErrorOccurredEventArgs("Empty result (send)."));
                }
            }

            if (e.Parameter == "reminder")
            {
                if (data["result"] != null)
                {
                    var result = "ok".Equals(data["result"].Value<string>());
                    FireRememberDiscussionPostCompleted(new RememberDiscussionPostEventArgs() { Result = result });
                }
                else
                {
                    FireErrorOccurred(new ErrorOccurredEventArgs("Empty result (reminder)."));
                }
            }

            if (e.Parameter == "delete")
            {
                if (data["result"] != null)
                {
                    var result = "ok".Equals(data["result"].Value<string>());
                    FireDeleteDiscussionPostCompleted(new DeleteDiscussionPostEventArgs() { Result = result });
                }
                else
                {
                    FireErrorOccurred(new ErrorOccurredEventArgs("Empty result (delete)."));
                }
            }
        }
        #endregion

        #region FireGetDiscussionCompleted
        private void FireGetDiscussionCompleted(GetDiscussionEventArgs e)
        {
            if (null != GetDiscussionCompleted)
            {
                GetDiscussionCompleted(this, e);
            }
        }
        #endregion

        #region FireSendDiscussionMessageCompleted
        private void FireSendDiscussionMessageCompleted(SendDiscussionMessageEventArgs e)
        {
            if (null != SendDiscussionMessageCompleted)
            {
                SendDiscussionMessageCompleted(this, e);
            }
        }
        #endregion

        #region FireRememberDiscussionPostCompleted
        private void FireRememberDiscussionPostCompleted(RememberDiscussionPostEventArgs e)
        {
            if (null != RememberDiscussionPostCompleted)
            {
                RememberDiscussionPostCompleted(this, e);
            }
        }
        #endregion

        #region FireDeleteDiscussionPostCompleted
        private void FireDeleteDiscussionPostCompleted(DeleteDiscussionPostEventArgs e)
        {
            if (null != DeleteDiscussionPostCompleted)
            {
                DeleteDiscussionPostCompleted(this, e);
            }
        }
        #endregion
    }
}
